package cn.com.libertymutual.core.http;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import cn.com.libertymutual.core.util.StringUtil;

public class HttpAndHttpsUtil {
	private static Logger logger = LoggerFactory.getLogger(HttpAndHttpsUtil.class);

	public final static String METHOD_GET = "GET";
	public final static String METHOD_POST = "POST";

	/**
	 * @author AoYi
	 *
	 *内部类-X509证书信任管理器类
	 */
	private static class MyTrustAnyX509TrustManager implements X509TrustManager {
		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return new X509Certificate[] {};
		}
	}

	/**
	 * @author AoYi
	 *
	 *内部类-主机名验证的基接口
	 */
	private static class TrustAnyHostnameVerifier implements HostnameVerifier {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}

	/**Remarks: 根据请求地址自动选请求相应[HTTP/HTTPS]协议, 发送post请求, JSON请求方式<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:23:00<br>
	 * Project：liberty_sale_plat<br>
	 * @param url 请求地址
	 * @param content RUL参数
	 * @param charset 编码
	 * @return JSON对象
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws IOException
	 */
	public static JSONObject postJsonReturnJson(String url, String content, String charset)
			throws NoSuchAlgorithmException, KeyManagementException, IOException {
		System.out.println("请求地址>>>" + url);
		System.out.println("请求内容>>>" + content);
		byte[] sendBytes = null;
		if (url.trim().toLowerCase().startsWith("https")) {
			sendBytes = httpsPost(url, content, charset, null);

		} else {
			sendBytes = httpPost(url, content, charset, null);
		}
		if (sendBytes == null)
			return null;
		String recString = new String(sendBytes, charset);
		JSONObject json = JSONObject.parseObject(recString);
		System.out.println("返回结果内容>>>" + json.toString());
		return json;

	}

	/**Remarks: 根据请求地址自动选请求相应[HTTP/HTTPS]协议, 发送post请求, JSON请求方式<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:23:00<br>
	 * Project：liberty_sale_plat<br>
	 * @param url 请求地址
	 * @param content RUL参数
	 * @param charset 编码
	 * @return JSON对象
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws IOException
	 */
	public static String postJsonReturnJsonSt(String url, String content, String charset)
			throws NoSuchAlgorithmException, KeyManagementException, IOException {
		logger.info("请求地址>>>{}", url);
		logger.info("请求内容>>>{}", content);
		byte[] sendBytes = null;
		if (url.trim().toLowerCase().startsWith("https")) {
			sendBytes = httpsPost(url, content, charset, null);

		} else {
			sendBytes = httpPost(url, content, charset, null);
		}
		if (sendBytes == null)
			return null;
		String recString = new String(sendBytes, charset);
		// JSONObject json = JSONObject.parseObject(recString);
		// System.out.println("返回结果内容>>>" + json.toString());
		return recString;

	}

	/**Remarks: 根据请求地址自动选请求相应[HTTP/HTTPS]协议, 发送post请求, RUL请求方式<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:24:19<br>
	 * Project：liberty_sale_plat<br>
	 * @param url 请求地址
	 * @param content RUL参数
	 * @param charset 编码
	 * @return 字符串
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws IOException
	 */
	public static String postFormReturnString(String url, String content, String charset)
			throws NoSuchAlgorithmException, KeyManagementException, IOException {
		System.out.println("请求地址>>>" + url);
		System.out.println("请求内容>>>" + content);
		byte[] sendBytes = null;
		if (url.trim().toLowerCase().startsWith("https")) {
			sendBytes = httpsPost(url, content, charset, "application/x-www-form-urlencoded;charset=utf-8 ");
		} else {
			sendBytes = httpPost(url, content, charset, "application/x-www-form-urlencoded;charset=utf-8 ");
		}
		if (sendBytes == null)
			return null;
		String recString = new String(sendBytes, charset);
		JSONObject json;
		try {
			json = JSONObject.parseObject(recString);
			recString = json.toJSONString();
		} catch (Exception e) {
			logger.info("postFormReturnJson返回数据转json失败,返回数据===>{}", recString);
		}
		System.out.println("返回结果内容>>>" + recString);
		return recString;

	}

	public static String obj2Param(Object data) {
		String returnData = null;
		if (data == null)
			return null;
		if (data instanceof String)
			return data.toString();
		Field[] fileds = data.getClass().getDeclaredFields();
		StringBuilder bu = new StringBuilder();
		try {
			for (Field f : fileds) {
				f.setAccessible(true);// 设置访问权限
				if (f.get(data) != null && !"serialVersionUID".equals(f.getName())) {
					bu.append(f.getName()).append("=").append(java.net.URLEncoder.encode(f.get(data).toString(), "UTF-8")).append("&");
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException | UnsupportedEncodingException e) {
			// Auto-generated catch block
			e.printStackTrace();
		}
		if (bu.length() > 0) {
			returnData = bu.toString();
			returnData = returnData.substring(0, returnData.lastIndexOf("&"));
		}
		return returnData;
	}

	/**Remarks: (微信)根据请求方式[GET/POST]使用HTTPS请求相应地址，返回JSON对象<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:05:25<br>
	 * Project：liberty_sale_plat<br>
	 * @param requestUrl 请求地址
	 * @param requestMethod 请求方式（GET、POST）
	 * @param outputStr 提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpsPost(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyTrustAnyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();

			if (StringUtils.isNotBlank(buffer.toString())) {
				jsonObject = JSONObject.parseObject(buffer.toString());
			}
		} catch (ConnectException ce) {
			logger.info("Weixin server connection timed out.");
		} catch (Exception e) {
			logger.info("https request error:{}", e);
		}
		return jsonObject;
	}

	/**Remarks: post方式请求服务器(HTTPS协议), 默认请求方式为JSON<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:10:17<br>
	 * Project：liberty_sale_plat<br>
	 * @param url 请求地址
	 * @param content RUL参数
	 * @param charset 编码
	 * @param contentType header请求格式
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws IOException
	 */
	public static byte[] httpsPost(String url, String content, String charset, String contentType)
			throws NoSuchAlgorithmException, KeyManagementException, IOException {
		if (StringUtils.isBlank(content)) {
			content = "";
		}
		URL console = new URL(url);
		HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();

		SSLContext sc = SSLContext.getInstance("SSL");
		sc.init(null, new TrustManager[] { new MyTrustAnyX509TrustManager() }, new java.security.SecureRandom());
		conn.setSSLSocketFactory(sc.getSocketFactory());

		conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
		conn.setRequestProperty("Connection", "Keep-Alive");
		if (StringUtils.isBlank(charset)) {
			charset = "UTF-8";
		}
		// 设置请求头信息
		conn.setRequestProperty("Charset", charset);
		// String BOUNDARY = "----------" + System.currentTimeMillis();
		// conn.setRequestProperty("Content-Type",
		// "multipart/form-data; boundary=" + BOUNDARY);

		conn.setRequestProperty("Content-Type", StringUtil.isEmpty(contentType) ? "application/json" : contentType);
		conn.setRequestProperty("Content-Length", String.valueOf(content.length()));
		conn.setDoOutput(true);
		conn.connect();
		// DataOutputStream out = new DataOutputStream(conn.getOutputStream());
		// out.write(content);
		OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
		out.write(content.toString());
		// 刷新、关闭
		out.flush();
		out.close();
		InputStream is = conn.getInputStream();
		if (is != null) {
			ByteArrayOutputStream outStream = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = is.read(buffer)) != -1) {
				outStream.write(buffer, 0, len);
			}
			is.close();
			return outStream.toByteArray();
		}
		return null;
	}

	/**Remarks: post方式请求服务器(HTTP协议), 默认请求方式为JSON<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:21:46<br>
	 * Project：liberty_sale_plat<br>
	 * @param url 请求地址
	 * @param content RUL参数
	 * @param charset 编码
	 * @param contentType header请求格式
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws IOException
	 */
	public static byte[] httpPost(String url, String content, String charset, String contentType)
			throws NoSuchAlgorithmException, KeyManagementException, IOException {
		URL console = new URL(url);
		HttpURLConnection conn = (HttpURLConnection) console.openConnection();
		conn.setRequestProperty("Connection", "Keep-Alive");
		// 设置请求头信息
		conn.setRequestProperty("Charset", "UTF-8");
		// String BOUNDARY = "----------" + System.currentTimeMillis();
		// conn.setRequestProperty("Content-Type",
		// "multipart/form-data; boundary=" + BOUNDARY);

		conn.setRequestProperty("Content-Type", StringUtil.isEmpty(contentType) ? "application/json" : contentType);
		conn.setRequestProperty("Content-Length", String.valueOf(content.length()));
		conn.setDoOutput(true);
		conn.connect();
		// DataOutputStream out = new DataOutputStream(conn.getOutputStream());
		// out.write(content);
		OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
		out.write(content.toString());
		// 刷新、关闭
		out.flush();
		out.close();
		InputStream is = conn.getInputStream();
		if (is != null) {
			ByteArrayOutputStream outStream = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = is.read(buffer)) != -1) {
				outStream.write(buffer, 0, len);
			}
			is.close();
			return outStream.toByteArray();
		}
		return null;
	}

	/**Remarks: (原始请求,默认请求地理位置)向指定 URL 发送POST方法的请求<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月20日上午11:53:38<br>
	 * Project：liberty_sale_plat<br>
	 * @param url 请求地址
	 * @param param URL参数(name1=value1&name2=value2)
	 * @param charset 编码
	 * @return 远程资源的响应结果
	 * @throws UnsupportedEncodingException
	 */
	public static String httpPost(String url, String param, String charset) throws UnsupportedEncodingException {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			// 设置接受的文件类型，*表示一切可以接受的
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			// 新添加的请求头编码
			conn.setRequestProperty("Accept-Charset", charset);
			// 设置通用的请求属性
			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	public static void main(String[] args) {

	}

}
